<?php

namespace App\Model;

use App\Toolys\CustomHttpException;
use EasySwoole\FastCache\Cache;
use EasySwoole\ORM\AbstractModel;
use EasySwoole\ORM\Exception\Exception;
use Throwable;

/**
 * RoleModel
 * Class RoleModel
 * Create With ClassGeneration
 * @property int $id //
 * @property string $pid //
 * @property string $name // 角色组名称
 * @property string $rule_ids // 权限
 * @property int $status // (0|1)禁用或启用
 * @property int weight // 权重
 */
class RoleModel extends BaseModel
{
	protected $tableName = 'role';
	const ROLESKEY = "admin-roles";

	public function addData(string $pid, string $name, string $rule_ids, int $status): self
	{
		$data = [
		    'pid'=>$pid,
		    'name'=>$name,
		    'rule_ids'=>$rule_ids,
		    'status'=>$status,
		];
		$model = new self($data);
		$model->save();
		return $model;
	}

    /**
     * @return array
     * @throws Exception
     * @throws Throwable
     * *    author 韩天尊
     */
    public function getRoles($id=0)
    {
        $result = [];
        $roles = $this->roles();
        $this->traverseRoles($roles, $result, $id);
        $result = $this->rule_sort($result, 1);
        return $result;
	}

    /** 冒泡排序
     * @param array $array
     * @param int $sortType
     * @return array
     * *    author 韩天尊
     */
    function rule_sort(array $array, int $sortType=0): array
    {
        $arrayLength = count($array)-1;
        for ($i=0; $i<$arrayLength; $i++){
            for($j=0; $j<$arrayLength-$i; $j++){
                if (isset($array[$j])&&isset($array[$j+1])){
                    if (($sortType===0)? ($array[$j]['weight'] > $array[$j+1]['weight']):($array[$j]['weight'] < $array[$j+1]['weight'])){
                        $container = $array[$j];
                        $array[$j] = $array[$j+1];
                        $array[$j+1] = $container;
                    }
                }
            }
        }
        return $array;
    }

    /** 角色关系合并可加字段带排序
     * @param array $menus
     * @param array $result
     * @param int $pid
     * *    author 韩天尊
     */
    function traverseRoles(array $menus, array &$result, $pid = 0)
    {
        foreach ($menus as $child) {
            // 子菜单的 pid = $pid
            // 说明它是 $pid 下面的子菜单
            if ($child['pid'] == $pid) {
                // 包装为成我们需要的格式
                $item = [
                    'id' => $child['id'],
                    'name' => $child['name'],
                    'pid' => $child['pid'],
                    'status' => $child['status'],
                    'rule_ids' => $child['rule_ids'],
                    'weight' => $child['weight'],
                    'children' => []
                ];
                // 递归上面的操作，装完 所有 属于 $pid 下面的子菜单
                $this->traverseRoles($menus, $item['children'], $child['id']);
                //排序
                if (!empty($item['children']) && (count($item['children'])>=2)){
                    $item['children'] = $this->rule_sort($item['children'], 1);
                }
                // 至此完成 $pid 级下的所有子菜单装入 result 中
                $result[] = $item;
            }
        }
    }

    /** 获取全部角色
     * @param string $key
     * @param string $value
     * @return array|mixed
     * @throws Exception
     * @throws Throwable
     * *    author 韩天尊
     *
     * 获取某个角色数据 = roles("id", 1);
     */
    public function roles(string $key="", $value="")
    {
        $data = json_decode(Cache::getInstance()->get(self::ROLESKEY), 1);
        if (empty($data)){
            $data = dbObjectToArray($this->all());
            if (!empty($data)){
                Cache::getInstance()->set(self::ROLESKEY, json_encode($data), 300);
            }
        }
        if (!empty($key) && !empty($data) && !empty($value)){
            foreach ($data as $datum){
                if ($datum[$key] == $value){
                    $data = $datum;break; }
            }
        }
        return $data;
    }

    /** 删除缓存
     * *    author 韩天尊
     */
    public function unsetCacheRolesKey()
    {
        if (Cache::getInstance()->get(self::ROLESKEY)){
            Cache::getInstance()->unset(self::ROLESKEY);
        }
    }

    /** 检测用户组权限
     * *    author 韩天尊
     * @param string $checkUrl
     * @param string $method
     * @param $role_id
     * @return bool
     * @throws CustomHttpException
     * @throws Exception
     * @throws Throwable
     */
    public function checkRoleRule(string $checkUrl, string $method, $role_id):bool
    {
        $role = arrayTransitionObject($this->roles("id", $role_id));
        if ($role->method == "*"){//超级管理组 无脑放行
            return true;}
        $rules = arrayTransitionObject((new RuleModel())->menus());
        $checkRule = null;
        foreach ($rules as $rule){
            if ($rule->rule==$checkUrl && strtoupper($rule->method)==strtoupper($method)){
                $checkRule = $rule;break;}}
        if (empty($checkRule)){customHttpException(401, "无此路由权限配置");}
        $role_ids = explode(",", $role->rule_ids);
        if (!in_array($checkRule->id, $role_ids)){customHttpException(401, "无权限调用");}
        if ($checkRule->status != 1){customHttpException(401, "该权限已关闭");}
        return true;
    }


}

